﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics.Contracts;

using SimpleIR;
using PInfoModel;

namespace PIPostAnalysis.UserQuery
{
	/// <summary>
	/// The info for all the parameters in a given method.
	/// </summary>
	public class ParameterInfo
	{
		/// <summary>
		/// The invoke identity that this parameter information is for.
		/// </summary>
		public readonly IRInvokeIdentity MethodID;

		/// <summary>
		/// Simple map from the names of paramemters to the current data we have on them.
		/// </summary>
		public List<SingleParamInfo> PNameDataMap;

		/// <summary>
		/// A list of the calls that occour in this.
		/// </summary>
		internal List<ParamInfoCallSite> CallSiteInfoForCallsInMethod;

		public ParameterInfo(IRInvokeIdentity invid)
		{
			this.MethodID = invid;
			this.PNameDataMap = new List<SingleParamInfo>();
			this.CallSiteInfoForCallsInMethod = new List<ParamInfoCallSite>();
		}

		public override string ToString()
		{
			StringBuilder sb = new StringBuilder(this.MethodID.ToString() + "\n");

			for(int i = 0; i < this.PNameDataMap.Count; ++i)
				sb.Append(this.PNameDataMap[i].ToString());

			return sb.ToString();
		}

		public static string StringifyAll(Dictionary<IRInvokeIdentity, ParameterInfo> pd)
		{
			StringBuilder sb = new StringBuilder();

			List<ParameterInfo> pil = new List<ParameterInfo>(pd.Values);
			pil.Sort((ParameterInfo p1, ParameterInfo p2) => p1.MethodID.ToString().CompareTo(p2.MethodID.ToString()));

			foreach(ParameterInfo pi in pil)
			{
				if(pi.MethodID.DefInClass.TypeDescription.IsBuiltinType)
					continue;

				sb.Append("\n------\n" + pi.ToString());
			}

			return sb.ToString();
		}
	}

	/// <summary>
	/// Information about a single call-site target in the method which this parameter is associated with.
	/// </summary>
	internal class ParamInfoCallSite
	{
		public readonly IRInvokeIdentity CalleeInv;

		public readonly IRSourceLocation CallLocation;

		/// <summary>
		/// Map from ids in the callee scope to ids in the caller scope
		/// </summary>
		public readonly Dictionary<MemLocID, HashSet<MemLocID>> MemLocsPassedInMap;

		public ParamInfoCallSite(IRInvokeIdentity inv, IRSourceLocation sl, Dictionary<MemLocID, HashSet<MemLocID>> mlpim)
		{
			this.CalleeInv = inv;
			this.CallLocation = sl;
			this.MemLocsPassedInMap = mlpim;
		}
	}
}
